# Most of this code is from https://github.com/KrauseFx/fastlane/blob/master/fastlane/Fastfile

fastlane_version '1.32.1'

desc "Run bundle install and tests"
lane :test do
  validate_repo(tool_name: detect_tool)
end

desc "Increment the version number of this gem"
lane :bump do |options|
  tool_name = options[:tool] || detect_tool
  path = "./lib/#{tool_name}/version.rb"

  latest_release = current_version(tool: tool_name)
  `open https://github.com/#{github_url(tool: tool_name)}/compare/#{latest_release}...master`

  local_version = version_get_podspec(path: path) # here, to not show the lane change

  puts "Live Version: #{latest_release}"
  puts "Local Version: #{local_version}"

  bump_type ||= 'minor' if prompt(text: "New Feature?", boolean: true)
  bump_type ||= 'patch' if bump_type.nil? && prompt(text: "Bugfix/Improvements?", boolean: true)

  if bump_type
    version_bump_podspec(path: path, bump_type: bump_type)
    git_commit(path: path,
               message: "Version Bump by fastlane")
    push_to_git_remote
  else
    puts "Doing nothing..."
  end
end

desc "Does everything that's needed for a release, this includes running tests and verifying the GitHub release"
lane :release do |options|
  # Fetching all information required for the release
  #
  tool_name = options[:tool] || detect_tool

  # Verifying RubyGems version
  #
  validate_repo(tool_name: tool_name)

  require "../lib/#{tool_name}/version"
  version = module_ref(tool_name: tool_name)::VERSION
  old_version = current_version(tool: tool_name)
  puts "Deploying #{tool_name} #{version}"
  if Gem::Version.new(version) <= Gem::Version.new(old_version)
    raise "Version number #{version} was already deployed"
  end

  # Git verification
  #
  ensure_git_status_clean
  ensure_git_branch(branch: 'master')
  git_pull
  push_to_git_remote


  # Build the gem
  #
  sh "rake build"


  # Preparing GitHub Release
  #
  version_name = "v#{version}"
  old_version_name = "v#{old_version}"

  github_release = get_github_release(url: github_url(tool: tool_name), version: version_name)
  if (github_release || {}).fetch('body', '').length == 0
    `open https://github.com/#{github_url(tool: tool_name)}/compare/#{old_version_name}...master`

    title = prompt(text: 'Title: ')
    description = prompt(text: "Please enter a changelog: ",
                         multi_line_end_keyword: "END")

    github_release = set_github_release(
        repository_name: github_url(tool: tool_name),
        name: [version_name, title].join(" "),
        tag_name: version_name,
        description: description,
        is_draft: false
    )
  end

  # Actual release
  #
  sh "gem push ../pkg/#{tool_name}-#{version}.gem"

  release_url = github_release['html_url']

  # After publishing
  #
  clipboard(value: release_url)

  puts "You can now tweet:".green
  puts "[#{tool_name}] #{github_release['name']} #{release_url}"
end

error do |lane, exception|
  if ENV['SLACK_URL']
    slack(channel: "testing", message: exception.to_s, success: false)
  end
end

desc "Verifies all tests pass and the current state of the repo is valid"
private_lane :validate_repo do |options|
  tool_name = options[:tool_name]

  # Verifying that no debug code is in the code base
  #
  ensure_no_debug_code(text: "pry", extension: ".rb", path: "./lib/") # debugging code
  ensure_no_debug_code(text: "TODO", extension: ".rb", path: "./lib/") # TODOs
  ensure_no_debug_code(text: "now: ", extension: ".rb", path: "./lib/") # rspec focus
  ensure_no_debug_code(text: "<<<<<<<", extension: ".rb", path: "./lib/") # Merge conflict

  rubocop if File.exist?("../.rubocop.yml") # some project don't yet use rubocop

  # Verifying the --help command
  #
  binary_path = File.join("..", "bin", tool_name)
  content = sh "#{binary_path} --help" # not using `sh` here as it doesn't go out of the help screen
  ["--version", tool_name].each do |current|
    raise "--help missing information: '#{current}'" unless content.include? current
  end

  # Running ruby things
  #
  sh "cd .. && bundle install"

  # Run the tests
  #
  sh "cd .. && rake spec"
end

desc "e.g. KrauseFx/fastlane"
private_lane :github_url do |options|
  ['samnung', options[:tool]].join("/")
end

desc "Get the version number of the last release"
private_lane :current_version do |options|
  puts "Checking the latest version on RubyGems"
  download(url: "https://rubygems.org/api/v1/gems/#{options[:tool]}.json")["version"]
end

desc "Detects the name of the tool based on the current directory"
private_lane :detect_tool do
  Dir["../*.gemspec"].last.match(/(\w+).gemspec/)[1]
end

desc "Get a reference to the module of this tool"
desc "This method can be overwritten by the individual Fastfiles of the tools (e.g. PEM)"
private_lane :module_ref do |options|
  Object.const_get(options[:tool_name].split('_').collect(&:capitalize).join)
end
